﻿#region 头部注释

/*************************************************************************************
     * 目标框架：       .NET Framework 4.5 - CLR 4.0.30319.42000 
     * 命名空间：       ICodeShare.UI.Converters
     * 一类名称：       DoubleToStringPercentConverter
     * 一版本号：       v1.0.0.0 
*************************************************************************************    
     * 机器名称：       DESKTOP-CS9U887
     * 一一作者：       FXH_PC
     * 创建时间：       2017/3/28 16:32:55
*************************************************************************************
     * 功能描述：       1.
*************************************************************************************
     * 修 改 人：     
     * 修改时间：
     * 修改描述：
     * 一一版本：
*************************************************************************************
 *Copyright @ FXH_PC 2017. All rights reserved.
*************************************************************************************/

#endregion //头部注释

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;

namespace ICodeShare.UI.Converters
{
    #region IValueConverter
    /// <summary>
    /// Double值转换成Percent String值
    /// </summary>
    /// <example>
    /// 1.引用该程序集，在xmal文件添加命名空间引用。
    ///   xmlns:cvts="http://schemas.extended.wpf.com/converters"
    /// 2.在xaml文件添加Resources。
    ///   <Window.Resources>
    ///   <cvts:DoubleToStringPercentConverter x:Key="cvtsDoubleToStringPercent"/>
    ///   </Window.Resources>
    /// 3.在xaml文件中指定Binding值的Converter
    ///    <TextBox Text="{Binding Width,ElementName=txtCompare,Converter={StaticResource cvtsDoubleToStringPercent}}"></TextBox>
    /// </example>
    [ValueConversion(typeof(double), typeof(string))]
    public class DoubleToStringPercentConverter : IValueConverter
    {
        #region Constant
        private const double TwoDigitsRoundingValue = 10;
        #endregion //Constant

        #region Base Class Overrides 基类方法重写
        /// <summary>
        /// Modifies the source data before passing it to the target for display
        /// in the UI.
        /// </summary>
        /// <param name="value">The source data being passed to the target.</param>
        /// <param name="targetType">The <see cref="T:System.Type" /> of data expected by
        /// the target dependency property.</param>
        /// <param name="parameter">An optional parameter to be used in the converter logic.</param>
        /// <param name="culture">The culture of the conversion.</param>
        /// <returns>The value to be passed to the target dependency property.</returns>
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (!(value is double))
                throw new ArgumentException("value should be of type double");
            double result = (double)value * 100;
            if (result < TwoDigitsRoundingValue)
            {
                return string.Format("{0:0.##}%", result);
            }
            else
            {
                return string.Format("{0:0.#}%", result);
            }
        }

        /// <summary>
        /// Modifies the target data before passing it to the source object.  This
        /// method is called only in <see cref="F:System.Windows.Data.BindingMode.TwoWay" />
        /// bindings.
        /// </summary>
        /// <param name="value">The target data being passed to the source.</param>
        /// <param name="targetType">The <see cref="T:System.Type" /> of data expected by
        /// the source object.</param>
        /// <param name="parameter">An optional parameter to be used in the converter logic.</param>
        /// <param name="culture">The culture of the conversion.</param>
        /// <returns>The value to be passed to the source object.</returns>
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null) return null;
            if (!(value is string))
                throw new ArgumentException("value should be of type string");

            string str = value.ToString();
            int percentIndex = str.IndexOf('%');
            if (percentIndex != -1)
            {
                str = str.Substring(0, percentIndex);
            }

            str = str.Replace(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator, CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator);
            str = this.TrimTrailingInvalidCharacters(str);

            double result = 0;
            double.TryParse(str, System.Globalization.NumberStyles.Any, CultureInfo.InvariantCulture, out result);

            result /= 100;

            return result;
        }
        #endregion //Base Class Overrides

        #region Private  Functions
        private string TrimTrailingInvalidCharacters(string str)
        {
            int validNumberLength = str.Length;
            int numberOfDecimalSeparators = 0;

            for (int i = 0; i < str.Length; i++)
            {
                if (str[i].ToString() == CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator)
                {
                    numberOfDecimalSeparators++;
                    if (numberOfDecimalSeparators > 1)
                    {
                        validNumberLength = i;
                        break;
                    }
                }
                else if (!char.IsDigit(str[i]))
                {
                    validNumberLength = i;
                    break;
                }
            }

            string result = str.Substring(0, validNumberLength);
            return result;
        }
        #endregion //Private  Functions
    }


    #endregion //IValueConverter
}
